﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;
using Enter.Services;
using Enter.Services.DataCache;

namespace Enter.Mvc.Base.ActionFilters
{
    [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class CacheActionAttribute : FilterAttribute, IActionFilter
    {
        private readonly ICache icache = Unity.GetInstance<ICache>();
        private string Key = string.Empty;
        public CacheActionAttribute()
        {

        }

        public CacheActionAttribute(string[] strlist)
        {
            this._Parameters = strlist;
            _AllParameters = false;
        }


        private int _CacheTime = 60;

        /// <summary>
        /// 缓存时间 单位秒 默认60秒
        /// </summary>
        public int CacheTime
        {
            get { return _CacheTime; }
            set { _CacheTime = value; }
        }

        private bool _IsUserId = false;

        /// <summary>
        /// 是否缓存用户Id 真缓存用户Id
        /// </summary>
        public bool IsUserId
        {
            get { return _IsUserId; }
            set { _IsUserId = value; }
        }


        private bool _IsCache = true;
        /// <summary>
        /// 是否使用缓存 默认开启
        /// </summary>
        public bool IsCache
        {
            get { return _IsCache; }
            set { _IsCache = value; }
        }

        private bool _AllParameters = true;

        /// <summary>
        /// 缓存所有参数 默认开启
        /// </summary>
        public bool AllParameters
        {
            get { return _AllParameters; }
            set { _AllParameters = value; }
        }


        private string[] _Parameters = null;

        /// <summary>
        /// 需要缓存的参数 启用后 缓存所有参数关闭
        /// </summary>
        public string[] Parameters
        {
            get { return _Parameters; }
            set { _Parameters = value; }
        }





        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (_IsCache && icache.IsCache())
            {
                string cachekey = filterContext.Controller.ViewBag.CacheActionAttribute_Key;
                if (!string.IsNullOrEmpty(cachekey))
                {
                    CacheActionObj obj = new CacheActionObj();
                    if (filterContext.Result is ViewResultBase)
                    {
                        ViewResultBase result = filterContext.Result as ViewResultBase;
                        if (result != null)
                        {
                            ICollection<string> keys = filterContext.Controller.ViewData.Keys;
                            ICollection<object> Valus = filterContext.Controller.ViewData.Values;
                            if (keys != null && keys.Count > 0)
                            {
                                obj.Keys = new List<string>(keys.Count);
                                obj.Valus = new List<object>(Valus.Count);
                                foreach (var key in keys)
                                {
                                    obj.Keys.Add(key);
                                }
                                foreach (var valu in Valus)
                                {
                                    obj.Valus.Add(valu);
                                }
                            }
                            obj.ActionType = CacheActionType.ViewResult;
                            obj.Model = filterContext.Controller.ViewData.Model;
                            obj.ViewName = result.ViewName;
                        }

                    }
                    else
                    {
                        obj.ActionType = CacheActionType.OtherResult;
                        obj.Model = filterContext.Result;
                    }
                    icache.Put(cachekey, obj, _CacheTime);
                }
            }

        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (_IsCache && icache.IsCache())
            {
                string cachekey = GetCacheKey1(filterContext.RequestContext.RouteData, filterContext.ActionParameters);
                filterContext.Controller.ViewBag.CacheActionAttribute_Key = cachekey;

                CacheActionObj obj = icache.Get<CacheActionObj>(cachekey);
                if (obj != null)
                {
                    if (obj.ActionType == CacheActionType.ViewResult)
                    {
                        ActionViewResult(filterContext, obj);
                    }
                    else
                    {
                        ActionOtherResult(filterContext, obj);
                    }
                }
            }

        }



        private string GetCacheKey1(RouteData paralist, IDictionary<string, object> ActionParameters)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("CacheAttribute");
            if (paralist != null && paralist.Values.Count > 0)
            {
                if (_AllParameters)
                {
                    foreach (var key in paralist.Values)
                    {
                        GetFormatKey(sb, key.Value);
                    }
                    foreach (var key in ActionParameters)
                    {
                        GetFormatKey(sb, key.Value);
                    }
                }
                else
                {
                    sb.AppendFormat("_{0}", paralist.Values["controller"]);
                    sb.AppendFormat("_{0}", paralist.Values["action"]);

                    if (_Parameters != null)
                    {
                        foreach (var key in _Parameters)
                        {
                            if (paralist.Values.ContainsKey(key))
                            {
                                GetFormatKey(sb, paralist.Values[key]);
                            }
                        }

                        foreach (var key in _Parameters)
                        {
                            if (ActionParameters.ContainsKey(key))
                            {
                                GetFormatKey(sb, ActionParameters[key]);
                            }
                        }
                    }
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// 格式化 Key
        /// </summary>
        /// <param name="sb"></param>
        /// <param name="key"></param>
        private void GetFormatKey(StringBuilder sb, object key)
        {
            if (key is string)
            {
                sb.AppendFormat("_{0}", key.ToString().Replace("_", "__"));
            }
            else
            {
                sb.AppendFormat("_{0}", key);
            }
        }

        /// <summary>
        /// ViewResult 返回处理情况
        /// </summary>
        /// <param name="filterContext"></param>
        /// <param name="obj"></param>
        private void ActionViewResult(ActionExecutingContext filterContext, CacheActionObj obj)
        {
            if (obj.Keys != null)
            {
                if (obj.Keys != null && obj.Keys.Count > 0)
                {
                    for (int i = 0, count = obj.Keys.Count; i < count; i++)
                    {
                        filterContext.Controller.ViewData[obj.Keys[i]] = obj.Valus[i];
                    }

                }
            }
            string _ViesName = null;
            if (!string.IsNullOrEmpty(obj.ViewName))
            {
                _ViesName = obj.ViewName;
            }
            filterContext.Controller.ViewData.Model = obj.Model;
            filterContext.Result = new ViewResult
            {
                ViewName = _ViesName,
                MasterName = null,
                ViewData = filterContext.Controller.ViewData,
                TempData = filterContext.Controller.TempData
            };
        }

        /// <summary>
        /// JsonResult 返回处理情况
        /// </summary>
        /// <param name="filterContext"></param>
        /// <param name="obj"></param>
        private void ActionOtherResult(ActionExecutingContext filterContext, CacheActionObj obj)
        {
            filterContext.Result = obj.Model as ActionResult;
        }
    }

    public enum CacheActionType
    {
        ViewResult = 1,
        OtherResult = 2,
    }

    internal class CacheActionObj
    {
        private CacheActionType _actionType = CacheActionType.ViewResult;


        public CacheActionType ActionType
        {
            get { return _actionType; }
            set { _actionType = value; }
        }

        private object _Model = null;

        /// <summary>
        /// 存储Model
        /// </summary>
        public object Model
        {
            get { return _Model; }
            set { _Model = value; }
        }

        private List<string> _Keys = null;

        /// <summary>
        /// ViewData ViewBag Key列表
        /// </summary>
        public List<string> Keys
        {
            get { return _Keys; }
            set { _Keys = value; }
        }

        private List<object> _Valus = null;

        /// <summary>
        /// ViewData ViewBag Value列表
        /// </summary>
        public List<object> Valus
        {
            get { return _Valus; }
            set { _Valus = value; }
        }

        private string _viewName = string.Empty;

        /// <summary>
        /// 跳转文件地址
        /// </summary>
        public string ViewName
        {

            get { return _viewName; }
            set { _viewName = value; }
        }

    }
}
